package MovieGuessingGame;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;



/** * A two-player game. */

class BaseServer {

	/** * The current player. */
	Player currentPlayer;
	//static ServerSocket listener = null;
	static SSLServerSocket listener = null;
	static ExecutorService player_startup_manager = null;
	static Map<String, Player> player_list = null;
	/**
	 * * Returns whether the current state of the board is such that one * of
	 * the players is a winner.
	 */
	public boolean hasWinner() {
		return false;
	}

	

	/**
	 * * Called by the player threads when a player tries to make a * move. This
	 * method checks to see if the move is legal: that * is, the player
	 * requesting the move must be the current player * and the square in which
	 * she is trying to move must not already * be occupied. If the move is
	 * legal the game state is updated * (the square is set and the next player
	 * becomes current) and * the other player is notified of the move so it can
	 * update its * client.
	 */

	public synchronized boolean legalMove(String selection, Player player) {
		System.out.println("legalMove()");
		if (player == currentPlayer){
			currentPlayer = currentPlayer.opponent;
			currentPlayer.otherPlayerMoved(selection);
			System.out.println("legalMove()=true");
			return true;
		}
		System.out.println("legalMove()=false");
		return false;
	}


    static void setUpPlayers(int port) throws IOException{
	    
    	synchronized(BaseServer.class) {
			if (BaseServer.listener == null) {
				SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
				BaseServer.listener = (SSLServerSocket) sslserversocketfactory.createServerSocket(port);
				System.out.println("Created Game Server Socket");
			}
			
			if (BaseServer.player_startup_manager == null ) {
				BaseServer.player_startup_manager = Executors.newFixedThreadPool(10);
			}
			
			if (BaseServer.player_list == null) {
				BaseServer.player_list = new HashMap<String, Player>();
			}
    	}
	    
		System.out.println("Movie Guessing Game Server is Running");
		
		try {
			while (true) {

				final Player player1 = new Player(BaseServer.listener.accept());
				System.out.println("DEBUG: accepted new player");
				
				Runnable task = new Runnable() {
					
					public void run() {
						
						synchronized (BaseServer.class) {
							System.out.println("DEBUG: entered first critical section");
							Collection<Player> players = BaseServer.player_list.values();
							StringBuilder to_send = new StringBuilder();
							Iterator<Player> it = players.iterator();
							while(it.hasNext()){
								Player p = it.next();
								if ( !p.isConnected() ){
									it.remove();
								}
								else if ( p.playing == false ){
									to_send.append(p.getPlayerName());
									to_send.append(",");
								}
							}
							
							player1.output.println(to_send);
							System.out.println("DEBUG: sent playerlist: " + to_send);
							
							System.out.println("DEBUG: exited first critical section");
						}
						
						String opp_name;
						
						try{
							System.out.println("DEBUG: waiting for req_opp string");
							opp_name = player1.getRequestedOpponent();
							System.out.println("DEBUG: req_opp is " + opp_name);
							if (opp_name == null ){
								System.out.println("got null, killing player");
								player1.closeSocket();
								return;
							}
							
						}catch (IOException e){
							System.out.println("exception while waiting on req_opp");
							synchronized ( BaseServer.class ) {
								if(BaseServer.player_list.containsKey(player1.getName()) ){
									BaseServer.player_list.remove(player1.getName());
								}
							}
							return;
						}
						
						synchronized( BaseServer.class ){
							System.out.println("DEBUG: entered second critical section");
							BaseServer.player_list.put(player1.getPlayerName(), player1);
							
							if ( BaseServer.player_list.containsKey(opp_name) ) {
								Player player2 = BaseServer.player_list.get(opp_name);
								
								if( player2.opponent == null ){
									player1.setOpponent(player2);
									player2.setOpponent(player1);
									
									BaseServer game = new BaseServer();
									MovieDB movieDB = new MovieDB();
									String movie = movieDB.getARandomMovie();
									
									player1.sendGameStart();
									player2.sendGameStart();							
									
									player1.setupGame(game, '1', movie);
									player2.setupGame(game, '2', movie);
									
									game.currentPlayer = player1;
									

									
									player1.start();
									player2.start();
								}
							}
							System.out.println("DEBUG: exited second critical section");
						}
						System.out.println("DEBUG: end of Runnable run()");
					}
				};
				
				BaseServer.player_startup_manager.submit(task);


				
//				Player player2 = new Player(game, listener.accept(), '2',movie);
//				player1.setOpponent(player2);
//				player2.setOpponent(player1);
//				game.currentPlayer = player1;
//				player1.start();
//				player2.start();
			}
		} finally {
			BaseServer.listener.close();
		}
	}
    
	public static void main(String[] args) throws Exception {
		setUpPlayers(8903);
		//setUpPlayers(8903);
//		ServerSocket listener = new ServerSocket(8903);
//		System.out.println("Movie Guessing Game Server is Running");
//		try {
//			while (true) {
//				BaseServer game = new BaseServer();
//				Player player1 = new Player(game, listener.accept(), '1');
//				Player player2 = new Player(game, listener.accept(), '2');
//				player1.setOpponent(player2);
//				player2.setOpponent(player1);
//				game.currentPlayer = player1;
//				player1.start();
//				player2.start();
//			}
//		} finally {
//			listener.close();
//		}
	}
}